package zx.lrn.notes.multi_threading;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 *
 * @ClassName: ForkJoinLrn
 * @Description: ForkJoin模式下的工作demo
 * @Author: zhaoxuan
 * @Date: 2020/3/12 1:29
 **/
public class ForkJoinLrn {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool();
        Integer is5050 = pool.invoke(new ForkJoinLrn().new ChildhoodGauss(1, 100));
        System.out.println(is5050);
    }

    /**
     * Fork-Join框架用来运行计算密集型任务，运用递归思想，将一个大型任务以1分2、2分4.。。不断分解直到子任务的规模适宜在一个线程中执行为止 Fork-Join框架采用“工作密取”的方法平衡每个子线程的工作负载
     * 在生产者-消费者设计中，所有消费者有一个共享的工作队列，而在工作密取设计中，每个消费者都有各自的双端队列。如果一个消费者完成了自己双端队列
     * 中的全部工作，那么它可以从其它消费者双端队列末尾秘密地获取工作。密取工作模式比传统的生产者-消费者模式具有更高的可伸缩性，这是因为工作者线
     * 程不会在单个共享的任务队列上发生竞争。在大多数时候，它们都只是访问自己的双端队列，从而极大地减少了竞争。当工作者线程需要访问另一个队列时， 它会从队列的尾部而不是头部获取工作，因此进一步降低了队列上的竞争程度。
     */
    class ChildhoodGauss extends RecursiveTask<Integer> {
        // 单次最大的任务规模
        private int threshold = 5;
        private int min;
        private int max;

        public ChildhoodGauss(int min, int max) {
            this.min = min;
            this.max = max;
        }

        @Override
        protected Integer compute() {
            int problemSize = max - min + 1;
            if (problemSize <= threshold) {
                return (min + max) * problemSize / 2;
                // 任务规模超限，拆分成两个子任务，分别执行后聚合结果
            } else {
                int middle = (min + max) >> 1;
                ChildhoodGauss left = new ChildhoodGauss(min, middle);
                ChildhoodGauss right = new ChildhoodGauss(middle + 1, max);
                invokeAll(left, right);
                return left.join() + right.join();
            }
        }
    }
}
